package org.cllib.ds;

public class Vector {
	private final static int CAPACITY_STEP = 5;
	
	private int size;
	
	private Object[] data = new Object[0];
	public Vector(){
		
	}
	
	public void add(final Object o){
		add(o , getSize());
	}
	
	public void add(final Object o ,final int index){
		if(o == null){
			throw new IllegalArgumentException("Vector does not accept null elements");
		}
		
		if(index < 0 || index > getSize()){
			throw new ArrayIndexOutOfBoundsException("Invalid index for new element [" + index + "] should be in the range [" + 0 + " , " + getSize() + "]");
		}
		
		ensureCapacity();
		
		System.arraycopy(data, index, data, index + 1, size - index);
		
		data[index] = o;
		size ++;
	}
	
	private void ensureCapacity(){
		if(getSize() + 1 > getCapacity()){
			Object[] newData = new Object[size + CAPACITY_STEP];
			System.arraycopy(data, 0, newData, 0, getSize());
			data = newData;
		}
	}
	
	public void set(final int index ,final Object o){
		if(o == null){
			throw new IllegalArgumentException("Vector does not accept null elements");
		}
		
		if(index < 0 || index >= getSize()){
			throw new ArrayIndexOutOfBoundsException("Invalid index for new element [" + index + "] should be in the range [" + 0 + " , " + (getSize() - 1) + "]");
		}
		
		data[index] = o;
	}
	
	public void remove(int index){
		if(index < 0 || index >= getSize()){
			throw new ArrayIndexOutOfBoundsException("Invalid index to remove element [" + index + "] should be in the range [" + 0 + " , " + (getSize() - 1) + "]");
		}
		
		System.arraycopy(data, index + 1, data, index, size - index);
		
		size --;
	}
	
	public int indexOf(Object o){
		if(o == null){
			return -1;
		}
		
		for (int i = 0; i < size; i++) {
			if(data[i] == o){
				return i;
			}
		}
		
		return -1;
	}
	
	public void clear(){
		size = 0;
	}
	
	public int getSize(){
		return size;
	}
	
	public int getCapacity(){
		return data.length;
	}
}
